package br.com.advance.automacao.services.job;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.advance.automacao.enumeration.TipoErro;
import br.com.advance.automacao.model.CLP;
import br.com.advance.automacao.model.Erro;
import br.com.advance.automacao.model.Evento;
import br.com.advance.automacao.model.MTBF;
import br.com.advance.automacao.model.Turno;
import br.com.advance.automacao.services.CLPConnectorFactory;
import br.com.advance.automacao.services.CLPService;
import br.com.advance.automacao.services.EventoService;
import br.com.advance.automacao.services.MTBFService;
import br.com.advance.automacao.services.RegistroErroSistemaService;
import br.com.advance.automacao.services.TurnoService;

@Service
public class ColetorFimDeTurnoJob {

	private static final Logger logger = Logger.getLogger(ColetorFimDeTurnoJob.class);


	@Autowired
	private CLPService clpService;

	@Autowired
	private EventoService eventoService;

	@Autowired
	private MTBFService mtbfService;

	@Autowired
	private CLPConnectorFactory clpConnectorFactory;

	@Autowired
	private TurnoService turnoService;
	
	@Autowired
	private RegistroErroSistemaService registroErroSistemaService;

	//Segundo Minuto Hora Dia Mês Dia_Da_Semana
	//@Scheduled(cron="0 11,12,14,15 10,11,12 * * *") - todos os dias do mês as 10,11 e 12 horas e 11,12,14 e 15 minutos e 0 segundo
	//@Scheduled(cron="0 30 7,15,23 * * *") // todos os dias do mês as 7, 15 e 23 horas
	@Scheduled(cron="0 0 6 * * *") // 6:00
	public void coletarDadosFimTurno1() {
		coletarDadosFimTurno();
	}
	@Scheduled(cron="0 20 14 * * *") // 14:20
	public void coletarDadosFimTurno2() {
		coletarDadosFimTurno();
	}
	@Scheduled(cron="0 40 22 * * *") // 22:40
	public void coletarDadosFimTurno3() {
		coletarDadosFimTurno();
	}
	/*@Scheduled(cron="0 25 16 * * *") // Teste
	public void coletarDadosFimTurno4() {
		logger.info("\n\n\nComecou o job de teste\n\n\n\n");
		coletarDadosFimTurno();
	}*/
	
	
	public void coletarDadosFimTurno() {
		logger.info("Comecou o job coletarDadosFimTurno.");

		Calendar calendar = defineData();

		Turno turno = defineTurno(calendar);
		// busca os clps ativos, independente de terem erros cadastrados ou não
		List<CLP> listaClps =  clpService.buscarTodosAtivosComErrosPossiveis();
		for (CLP clp : listaClps) {
			coletarDadosCLP(calendar, turno, clp);
		}
	}

	@Transactional(propagation=Propagation.REQUIRED)
	public String coletarDadosFimTurno(Long idCLP) {
		logger.info("Coletando dados do CLP id: " + idCLP);

		Calendar calendar = defineData();

		Turno turno = defineTurno(calendar);

		CLP clp = clpService.buscarPorIdComErros(idCLP);
		return coletarDadosCLP(calendar, turno, clp);
	}

	private Turno defineTurno(Calendar calendar) {
		Turno turno = turnoService.buscarTurnoPeloHorario(calendar.getTime());
		logger.info("Turno definido: ID: " + turno.getId() + " Hora de inicio: " + turno.getHoraInicio() + " Hora de fim: " + turno.getHoraFim() + " Codigo:"
				+ turno.getCodigo());
		return turno;
	}

	private Calendar defineData() {
		// procura turno atual
		Calendar calendar = new GregorianCalendar();
		calendar.setTimeInMillis(System.currentTimeMillis());
		calendar.add(Calendar.HOUR_OF_DAY, -6);
		return calendar;
	}

	private String coletarDadosCLP(Calendar calendar, Turno turno, CLP clp) {
		// se o clp estiver ativo, sem erro cadastrado, um erro é logado
		if(clp.getErros().isEmpty()) {
			logger.error("CLP ID: " + clp.getId() + " IP: " + clp.getIp() + " nao possui codigos de erros cadastrado.");
			registroErroSistemaService.criar(TipoErro.ERROS_EQUIPAMENTOS, "CLP ID: " + clp.getId() + " IP: " 
			+ clp.getIp() + " nao possui codigos de erros cadastrado.");
			return "CLP ID: " + clp.getId() + " IP: " + clp.getIp() + " nao possui codigos de erros cadastrado.";
		} else {
			logger.info("Obtendo dados do CLP ID: " + clp.getId() + " IP: " + clp.getIp());
			// essa variavel ira controlar se o clp possui algum erro cadastrado ativo.
			// se nao tiver nenhuma, um erro eh logado.
			Boolean erroAtivo = Boolean.FALSE;
			for (Erro erro : clp.getErros()) {
				if (erro.getAtivo()) {
					erroAtivo = Boolean.TRUE;
					break;
				}
			}
			if(!erroAtivo) {
				logger.error("CLP ID: " + clp.getId() + " IP: " + clp.getIp() + " nao possui codigos de erros ativos.");
				registroErroSistemaService.criar(TipoErro.ERROS_EQUIPAMENTOS, "CLP ID: " + clp.getId() + 
						" IP: " + clp.getIp() + " nao possui codigos de erros ativos.");
				return "CLP ID: " + clp.getId() + " IP: " + clp.getIp() + " nao possui codigos de erros ativos.";
			}
			Object[] retorno = clpConnectorFactory.getCLPConector(clp.getFabricante()).buscarEventosFimTurno(clp, calendar.getTime(), turno);
			if(retorno != null && retorno[0] != null && !((List) retorno[0]).isEmpty()) {
				// garante que não existem dados ja gravados para aquele turno, data e clp
				eventoService.deletarEventosPorClpDataTurno(turno.getId(), calendar.getTime(), clp.getId());
				@SuppressWarnings("unchecked")
				List<Evento> eventos = (List<Evento>) retorno[0];
				for(Evento evento : eventos) {
					eventoService.criar(evento);
				}
				mtbfService.deletarMTBFPorClpDataTurno(turno.getId(), calendar.getTime(), clp.getId());
				if(retorno[1] != null) {
					mtbfService.criar((MTBF) retorno[1]);	
				}
			} else {
				logger.warn("Nao foram encontrados dados para o CLP ID: "+ clp.getId() + " IP: " + clp.getIp() + " Nome: " + clp.getNome());
				registroErroSistemaService.criar(TipoErro.ERROS_EQUIPAMENTOS, "Nao foram encontrados dados para o CLP ID: "+ clp.getId() 
						+ " IP: " + clp.getIp() + " Nome: " + clp.getNome());
				return "Nao foram encontrados dados para o CLP ID: "+ clp.getId() + " IP: " + clp.getIp() + " Nome: " + clp.getNome();
			}
		}
		return null;
	}

	//Segundo Minuto Hora Dia Mês Dia_Da_Semana
	/*@Scheduled(cron="0 * * * * *") // todos os dias do mês as 7, 15 e 23 horas
	@Transactional("transactionManager")
	public void teste() {
		coletarDadosFimTurno();
	}*/
}
